﻿using JewererBasic.BO;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace JewererBasic.Models
{
    public class Product
    {
        public Product()
        {
            this.PRODUCT_COMPONENT = new List<Product_Component>();
            this.PRODUCT_MOULD = new List<Product_Mould>();
            this.PRODUCT_PROCESS = new List<Product_Process>();
            this.PRODUCT_STONE = new List<Product_Stone>();            
        }

        #region Properties
        [Required(ErrorMessage="Please fill Product_ID")]
        [MaxLength(30,ErrorMessage="Max lenght: 30 letters"), MinLength(6, ErrorMessage="Min length: 6 letters")]
        public string Id { get; set; }

        [Required]
        public Nullable<int> IdKind { get; set; }

        [Range(0, 1000,ErrorMessage="Range: 0-2000")]
        public Nullable<double> Size { get; set; }

        [Required(ErrorMessage = "Please choose Image")]
        public string Drawing { get; set; }

        [Required]
        public Nullable<int> IdUnit { get; set; }

        [Required]
        public Nullable<int> IdType { get; set; }

        [Range(0, 10000, ErrorMessage="Metal Weight: 0-10000")]
        public Nullable<double> MetalWeight { get; set; }
        [Range(0, 10000, ErrorMessage = "Total Weight: 0-10000")]
        public Nullable<double> TotalWeight { get; set; }
        
        [Required]
        public Nullable<int> IdGamma { get; set; }

        public string Remark { get; set; }
        
        public HttpPostedFileBase MyFile { get; set; }

        [List_Product_Component_Duplicate(ErrorMessage="Components are duplicated")]
        [List_Product_Component_Validation(ErrorMessage = "Only 1 Component is required")]
        public virtual List<Product_Component> PRODUCT_COMPONENT { get; set; }

        [List_Product_Mould_Duplicate(ErrorMessage="Moulds are duplicated")]
        public virtual List<Product_Mould> PRODUCT_MOULD { get; set; }

        [List_Product_Process_Validation(ErrorMessage="At least 1 Process")]
        public virtual List<Product_Process> PRODUCT_PROCESS { get; set; }
      
        [List_Product_Stone_Duplicate(ErrorMessage="Stones are duplicated")]
        public virtual List<Product_Stone> PRODUCT_STONE { get; set; }

        public TYPE TYPE { get; set; }
        public UNIT UNIT { get; set; }
        public GAMMA GAMMA { get; set; }
        public KIND KIND { get; set; }
        #endregion

        public static PRODUCT Convert(Product source)
        {
            PRODUCT des = new PRODUCT();
            des.Drawing=source.Drawing;
            des.Id=source.Id;
            des.IdGamma=source.IdGamma;
            des.IdKind=source.IdKind;
            des.IdType=source.IdType;
            des.IdUnit=source.IdUnit;
            des.MetalWeight=source.MetalWeight;
            des.Remark=source.Remark;
            des.Size=source.Size;
            des.TotalWeight=source.TotalWeight;

            if(source.PRODUCT_COMPONENT!=null)
            {
                foreach (var item in source.PRODUCT_COMPONENT)
	            {
                    PRODUCT_COMPONENT pc=Product_Component.Convert(item);
                    pc.IdProduct=source.Id;
                    des.PRODUCT_COMPONENT.Add(pc);
	            }
            }
            if(source.PRODUCT_MOULD!=null)
            {
                foreach (var item in source.PRODUCT_MOULD)
	           {
                    PRODUCT_MOULD pm = Product_Mould.Convert(item);
                    pm.IdProduct=source.Id;
                    des.PRODUCT_MOULD.Add(pm);
	            }
            }
            if(source.PRODUCT_PROCESS!=null)
            {
                foreach (var item in source.PRODUCT_PROCESS)
	           {
                    PRODUCT_PROCESS pp = Product_Process.Convert(item);
                    pp.IdProduct=source.Id;
                    des.PRODUCT_PROCESS.Add(pp);
	            }
            }
            if(source.PRODUCT_STONE!=null)
            {
                foreach (var item in source.PRODUCT_STONE)
	           {
                    PRODUCT_STONE pm = Product_Stone.Convert(item);
                    pm.IdProduct=source.Id;
                    des.PRODUCT_STONE.Add(pm);
	            }
            }
            return des;
        }

        public static Product Convert(PRODUCT source)
        {
            Product des = new Product();
            des.Drawing=source.Drawing;
            des.Id=source.Id;
            des.IdGamma=source.IdGamma;
            des.IdKind=source.IdKind;
            des.IdType=source.IdType;
            des.IdUnit=source.IdUnit;
            des.MetalWeight=source.MetalWeight;
            des.Remark=source.Remark;
            des.Size=source.Size;
            des.TotalWeight=source.TotalWeight;
            des.KIND = new KIND() { Id = source.KIND.Id, Name = source.KIND.Name };
            des.UNIT = new UNIT() { Id = source.UNIT.Id, Name = source.UNIT.Name };
            des.GAMMA = new GAMMA { Id = source.GAMMA.Id, Name = source.GAMMA.Name };
            des.TYPE = new TYPE() { Id = source.TYPE.Id, Name = source.TYPE.Name };

            if(source.PRODUCT_COMPONENT!=null)
            {
                foreach (var item in source.PRODUCT_COMPONENT)
	            {
                    Product_Component pc=Product_Component.Convert(item);
                    des.PRODUCT_COMPONENT.Add(pc);
	            }
            }
            if(source.PRODUCT_MOULD!=null)
            {
                foreach (var item in source.PRODUCT_MOULD)
	           {
                    Product_Mould pm = Product_Mould.Convert(item);
                    des.PRODUCT_MOULD.Add(pm);
	            }
            }
            if(source.PRODUCT_PROCESS!=null)
            {
                foreach (var item in source.PRODUCT_PROCESS)
	           {
                    Product_Process pp = Product_Process.Convert(item);
                    des.PRODUCT_PROCESS.Add(pp);
	            }
            }
            if(source.PRODUCT_STONE!=null)
            {
                foreach (var item in source.PRODUCT_STONE)
	           {
                    Product_Stone pm = Product_Stone.Convert(item);
                    des.PRODUCT_STONE.Add(pm);
	            }
            }
            return des;
        }
    }

    public class Product_Component
	{
        [Required(ErrorMessage="Please fill Component_ID")]
        [Component_Id_Validation(ErrorMessage="Component_Id isn't existed in DB")]
        public string IdComponent { get; set; }
        
        [Required(ErrorMessage="Please fill Component_Weight")]
        public double Weight { get; set; }

        public static PRODUCT_COMPONENT Convert(Product_Component source)
        {
            PRODUCT_COMPONENT des=new PRODUCT_COMPONENT();
            des.IdComponent=source.IdComponent;
            des.Weight=source.Weight;
            return des;
        }

        public static Product_Component Convert(PRODUCT_COMPONENT source)
        {
            Product_Component des=new Product_Component();
            des.IdComponent=source.IdComponent;
            des.Weight=source.Weight;
            return des;
        }
	}
    public class Product_Mould
	{
        [Required(ErrorMessage="Please fill Mould_ID")]
        [Mould_Id_Validation(ErrorMessage="Mould_Id isn't existed in DB")]
        public string IdMould { get; set; }
        [Required(ErrorMessage="Please fill Mould_Qty")]
        public int Qty { get; set; }

        public static Product_Mould Convert(PRODUCT_MOULD source)
        {
            Product_Mould des=new Product_Mould();
            des.IdMould=source.IdMould;
            des.Qty=source.Qty;
            return des;
        }

        public static PRODUCT_MOULD Convert(Product_Mould source)
        {
            PRODUCT_MOULD des=new PRODUCT_MOULD();
            des.IdMould=source.IdMould;
            des.Qty=source.Qty;
            return des;
        }
	}
    public class Product_Process
	{        
        public int IdProcess { get; set; }
        [Required(ErrorMessage="Please fill Process")]
        [Process_Name_Validation(ErrorMessage="Process isn't existed in DB")]
        public string ProcessName { get; set; }
        [Range(0, 10000, ErrorMessage="Process Time: 0-10000")]
        public int Time { get; set; }

        public static Product_Process Convert(PRODUCT_PROCESS source)
        {
            Product_Process des=new Product_Process();
            des.IdProcess=source.IdProcess;
            des.Time=source.Time;
            des.ProcessName=source.PROCESS.Name;
            return des;
        }

        public static PRODUCT_PROCESS Convert(Product_Process source)
        {
            PRODUCT_PROCESS des=new PRODUCT_PROCESS();
            des.IdProcess=source.IdProcess;
            des.Time=source.Time;
            return des;
        }
	}
    public class Product_Stone
	{
        [Required(ErrorMessage = "Please fill this field")]
        [Stone_Id_Validation(ErrorMessage="Stone_Id isn't existed in DB")]
        public string IdStone { get; set; }
        [Required(ErrorMessage="Please fill Stone_Qty")]
        public int Qty { get; set; }

        [Required(ErrorMessage="Please fill Stone_Weight")]
        public double Weight { get; set; }

        public static Product_Stone Convert(PRODUCT_STONE source)
        {
            Product_Stone des=new Product_Stone();
            des.IdStone=source.IdStone;
            des.Qty=source.Qty;
            des.Weight = source.Weight;
            return des;
        }

        public static PRODUCT_STONE Convert(Product_Stone source)
        {
            PRODUCT_STONE des=new PRODUCT_STONE();
            des.IdStone=source.IdStone;
            des.Qty=source.Qty;
            des.Weight = source.Weight;
            return des;
        }
	}

    #region Validation: Check duplicate in List
    public class List_Product_Mould_Duplicate : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            List<Product_Mould> lst = (List<Product_Mould>)value;
            if (lst == null)
                return true;
            for (int i = 0; i < lst.Count - 1; i++)
            {
                for (int j = i + 1; j < lst.Count; j++)
                {
                    if (lst[i].IdMould.Equals(lst[j].IdMould) == true)
                        return false;
                }
            }
            return true;
        }
    }
    public class List_Product_Stone_Duplicate : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            List<Product_Stone> lst = (List<Product_Stone>)value;
            if (lst == null)
                return true;
            for (int i = 0; i < lst.Count - 1; i++)
            {
                for (int j = i + 1; j < lst.Count; j++)
                {
                    if (lst[i].IdStone.Equals(lst[j].IdStone) == true)
                        return false;
                }
            }
            return true;
        }
    }
    public class List_Product_Component_Duplicate: ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            List<Product_Component> lst = (List<Product_Component>)value;
            if (lst == null)
                return true;
            for (int i = 0; i < lst.Count-1; i++)
            {
                for (int j = i+1; j < lst.Count; j++)
                {
                    if (lst[i].IdComponent.Equals(lst[j].IdComponent) == true)
                        return false;
                }
            }
            return true;
        }
    }
    #endregion

    public class List_Product_Component_Validation : ValidationAttribute
    {
        public override bool IsValid(object value)
        {
            List<Product_Component> lst = (List<Product_Component>)value;
            if (lst == null)
                return false;   
            if (lst.Count == 1)
                return true;
            return false;
        }
    }

    public class List_Product_Process_Validation : ValidationAttribute
    {
        // Have to override IsValid
        public override bool IsValid(object value)
        {
            List<Product_Process> lst = (List<Product_Process>)value;
            if (lst == null)
                return false;
            if (lst.Count >0)
                return true;
            return false;
        }
    }    

    public class Component_Id_Validation:ValidationAttribute
    {
        public override bool IsValid(object value)
        {           
            string id=(string)value;
            CommonServiceImp commonService = new CommonServiceImp();
            return commonService.IsComponentExist(id);
        }
    }

    public class Stone_Id_Validation: ValidationAttribute
    {        
 	    public override bool IsValid(object value)
        {           
            string id=(string)value;
            CommonServiceImp commonService = new CommonServiceImp();
            return commonService.IsStoneExist(id);
        }
    }

    public class Mould_Id_Validation: ValidationAttribute
    {
        public override bool IsValid(object value)
        {
 	        string id=(string)value;
            CommonServiceImp commonService = new CommonServiceImp();
            return commonService.IsMouldExist(id);
        }
    }

    public class Process_Name_Validation: ValidationAttribute
    {
        public override bool IsValid(object value)
        {
 	        string processName=(string)value;
            CommonServiceImp commonService = new CommonServiceImp();
            return commonService.IsProcessNameExist(processName);
        }
    }
}